#include "protocol.h"
#include "stdio.h"
#include "string.h"
#include "app_include.h"
#include "data_transmit.h"

uint32_t send_sn = 0;


static uint32_t get_pack_check(uint8_t *buf,uint32_t length)
{
	int i = 0;
	uint32_t sum = 0;
	for(i = 0; i < length;i++)
	{
		sum += buf[i];
	}
	return sum;
}


uint32_t protocol_sensor_info_pack(uint8_t *buf,uint32_t buf_size,void *info)
{
	if(buf == NULL || buf_size < sizeof(protocol_sensor_info_t) || info == NULL)
	{
		return 0;
	}
	protocol_sensor_info_t pack;
	protocol_sensor_info_pack_t *ptr = (protocol_sensor_info_pack_t*)info;


	pack.header.magic_num = 0xA55A;
	pack.header.pack_type = PACK_TYPE_SENSOR_INFO;
	pack.header.pack_len = sizeof(protocol_sensor_info_t);
	pack.header.pack_sn = send_sn++;
	//header
	memcpy((uint8_t*)&pack.pack,(uint8_t*)ptr,sizeof(protocol_sensor_info_pack_t));
	pack.crc32 = get_pack_check((uint8_t*)&pack,sizeof(protocol_sensor_info_t) - sizeof(uint32_t));
	memcpy(buf,(uint8_t*)&pack,sizeof(protocol_sensor_info_t));
	return sizeof(protocol_sensor_info_t);
}


uint32_t protocol_input_info_pack(uint8_t *buf,uint32_t buf_size,void *info)
{
	if(buf == NULL || buf_size < sizeof(protocol_input_info_t) || info == NULL)
	{
		return 0;
	}
	protocol_input_info_t pack;
	protocol_input_info_pack_t *ptr = (protocol_input_info_pack_t*)info;


	pack.header.magic_num = 0xA55A;
	pack.header.pack_type = PACK_TYPE_INPUT_INFO;
	pack.header.pack_len = sizeof(protocol_input_info_t);
	pack.header.pack_sn = send_sn++;
	//header
	memcpy((uint8_t*)&pack.pack,(uint8_t*)ptr,sizeof(protocol_input_info_pack_t));
	pack.crc32 = get_pack_check((uint8_t*)&pack,sizeof(protocol_input_info_t) - sizeof(uint32_t));
	memcpy(buf,(uint8_t*)&pack,sizeof(protocol_input_info_t));
	return sizeof(protocol_input_info_t);
}

uint32_t protocol_expect_info_pack(uint8_t *buf,uint32_t buf_size,void *info)
{
	if(buf == NULL || buf_size < sizeof(protocol_expect_info_t) || info == NULL)
	{
		return 0;
	}
	protocol_expect_info_t pack;
	protocol_expect_info_pack_t *ptr = (protocol_expect_info_pack_t*)info;


	pack.header.magic_num = 0xA55A;
	pack.header.pack_type = PACK_TYPE_EXPECT_INFO;
	pack.header.pack_len = sizeof(protocol_expect_info_t);
	pack.header.pack_sn = send_sn++;
	//header
	memcpy((uint8_t*)&pack.pack,(uint8_t*)ptr,sizeof(protocol_expect_info_pack_t));
	pack.crc32 = get_pack_check((uint8_t*)&pack,sizeof(protocol_expect_info_t) - sizeof(uint32_t));
	memcpy(buf,(uint8_t*)&pack,sizeof(protocol_expect_info_t));
	return sizeof(protocol_expect_info_t);
}




uint32_t protocol_print_pack(uint8_t *buf,uint32_t buf_size,const char *fmt,uint32_t fmt_length)
{
	if(buf == NULL || buf_size < sizeof(protocol_header_t)+4 || fmt == NULL || fmt_length == 0)
	{
		return 0;
	}
	uint32_t ret = 0;
	uint32_t offset = 0;
	
	protocol_header_t header;
	header.magic_num = 0xA55A;
	header.pack_type = PACK_TYPE_PRINT_LOG;
	header.pack_len = sizeof(protocol_header_t) + fmt_length + sizeof(uint32_t);
	header.pack_sn = send_sn++;		
	memcpy(buf+offset,(uint8_t*)&header,sizeof(protocol_header_t));
	/*copy the header data*/
	offset += sizeof(protocol_header_t);
	
	memcpy(buf+offset,fmt,fmt_length);
	offset += fmt_length;
	union
	{
		uint32_t u32_;
		uint8_t u8_[4];
	}u32tou8;
	u32tou8.u32_ = get_pack_check(buf,offset);
	memcpy(buf+offset,u32tou8.u8_,4);
	offset += 4;
	ret = offset;
	return ret;
}

static uint8_t digital_twin_recv_buf[128] = {0};

void digital_twin_init(void)
{
	digital_twin_start_recv(digital_twin_recv_buf,sizeof(digital_twin_recv_buf));
}


int8_t digital_twin_recv_parse(uint16_t len)
{
	if( len < sizeof(protocol_header_t) + sizeof(uint32_t) )
	{
		return 1;
	}
	
	protocol_header_t header;	
	memcpy(&header,digital_twin_recv_buf,sizeof(protocol_header_t));
	
	if(header.magic_num == 0xA55A)
	{
		if( header.pack_len != len )
		{
			return -3;
		}
		
		uint32_t cal_check = get_pack_check(digital_twin_recv_buf,len - 4);
		union 
		{
			uint32_t u32_;
			uint8_t u8_[4];
		}pack_check;
		
		memcpy(pack_check.u8_,digital_twin_recv_buf+len-4,4);
		if( cal_check != pack_check.u32_)
		{
			DEBUG_PRINTF("check error pack:%d cal:%d",pack_check.u32_,cal_check);
		}
		
		
		
		if( header.pack_type == PACK_TYPE_FC_EXPERIMENT_CMD )
		{
			uint8_t type = digital_twin_recv_buf[sizeof(protocol_header_t)];
			uint8_t command = digital_twin_recv_buf[sizeof(protocol_header_t) + 1];
			
			DEBUG_PRINTF("recv experiment cmd,%d type:%d",command,type);
		}
		
	}
	else
	{
		DEBUG_PRINTF("invalid pack");
		return 2;
	}
	return 0;
}


__WEAK uint8_t digital_twin_send_data(uint8_t *buf,uint16_t length)
{
	return 0;
}

__WEAK void digital_twin_start_recv(uint8_t *buf,uint16_t length)
{
}

